home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CBASE102.ARJ / LOCKB.C < prev    next >
Text File  |  1991-09-23  |  8KB  |  332 lines

  1. /*    Copyright (c) 1989 Citadel    */
  2. /*       All Rights Reserved        */
  3.  
  4. /* #ident    "@(#)lockb.c    1.5 - 91/09/23" */
  5.  
  6. #include <ansi.h>
  7.  
  8. /* ansi headers */
  9. #include <errno.h>
  10. #ifdef AC_STDDEF
  11. #include <stddef.h>
  12. #endif
  13.  
  14. /* local headers */
  15. #include "blkio_.h"
  16.  
  17. /* system headers */
  18. #if OPSYS == OS_AMIGADOS    /* Amiga DOS =================================*/
  19.  
  20. #elif OPSYS == OS_MAC        /* Macintosh =================================*/
  21.  
  22. #elif OPSYS == OS_DOS        /* DOS =======================================*/
  23. #include <limits.h>        /* LONG_MAX definition */
  24. #if CCOM == CC_BC        /* Borland C++ -------------------------------*/
  25. #include <io.h>
  26. #define LK_UNLCK    (0)    /* unlock */
  27. #define LK_LOCK        (1)    /* lock */
  28. #define LK_NBLCK    (2)    /* non-blocking lock */
  29. #define LK_RLCK        (3)    /* read lock */
  30. #define LK_NBRLCK    (4)    /* non-blocking read lock */
  31. #elif CCOM == CC_MSC || CCOM == CC_MSQC    /* Microsoft C or Quick C ------------*/
  32. #include <sys\locking.h>
  33. #include <io.h>
  34. #endif
  35. #elif OPSYS == OS_UNIX        /* UNIX ======================================*/
  36. #include <fcntl.h>
  37. #ifdef AC_PROTO
  38. int fcntl(int fd, int cmd, ...);
  39. #else
  40. int fcntl();
  41. #endif
  42. #elif OPSYS == OS_VMS        /* VMS =======================================*/
  43.  
  44. #endif
  45.  
  46. /*man---------------------------------------------------------------------------
  47. NAME
  48.      lockb - block file record locking
  49.  
  50. SYNOPSIS
  51.      #include <blkio.h>
  52.  
  53.      int lockb(bp, ltype, start, len)
  54.      BLKFILE *bp;
  55.      int ltype;
  56.      bpos_t start;
  57.      bpos_t len;
  58.  
  59. DESCRIPTION
  60.      The lockb function will allow segments of a block file to be
  61.      locked.  bp is the BLKFILE pointer for the file to be locked.
  62.  
  63.      ltype indicates the target status of the lock.  The lock types
  64.      available are:
  65.  
  66.        B_UNLCK unlock block file segment
  67.        B_RDLCK lock block file segment for reading
  68.        B_WRLCK lock block file segment for reading and writing
  69.        B_RDLKW lock block file segment for reading (wait)
  70.        B_WRLKW lock block file segment for reading and writing (wait)
  71.  
  72.      For the lock types which wait, lockb will not return until the
  73.      lock is available.  For the lock types which do not wait, if the
  74.      lock is unavailable because of a lock held by another process  a
  75.      value of -1 is returned and errno set to EAGAIN.
  76.  
  77.      start is the first block to lock.  len is the number of
  78.      contiguous blocks including and following block start to be
  79.      locked or unlocked.  A lock may be set to extend to the end of
  80.      the file by setting len to zero.
  81.  
  82.      The buffers are flushed before unlocking.
  83.  
  84.      lockb will fail if one or more of the following is true:
  85.  
  86.      [EAGAIN]       ltype is B_RDLCK and the file segment to be locked
  87.                     is already write locked by another process, or
  88.                     ltype is B_WRLCK and the file segment to be locked
  89.                     is already read or write locked by another
  90.                     process.
  91.      [EINVAL]       bp is is not a valid BLKFILE pointer.
  92.      [EINVAL]       ltype is not one of the valid lock types.
  93.      [BENOPEN]      bp is not open.
  94.      [BENOPEN]      ltype is B_RDLCK or B_RDLKW and bp is not opened
  95.                     for reading or ltype is B_WRLCK or B_WRLKW and bp
  96.                     is not open for writing.
  97.  
  98. DIAGNOSTICS
  99.      Upon successful completion, a value of 0 is returned.  Otherwise,
  100.      a value of -1 is returned, and errno set to indicate the error.
  101.  
  102. ------------------------------------------------------------------------------*/
  103. #ifdef AC_PROTO
  104. int lockb(BLKFILE *bp, int ltype, bpos_t start, bpos_t len)
  105. #else
  106. int lockb(bp, ltype, start, len)
  107. BLKFILE *bp;
  108. int ltype;
  109. bpos_t start;
  110. bpos_t len;
  111. #endif
  112. {
  113. #if OPSYS == AMIGADOS
  114.  
  115. #elif OPSYS == OS_DOS
  116.     long    length    = 0;    /* length in bytes of segment to lock */
  117.     int    mode    = 0;    /* file locking mode */
  118.     long    offset    = 0;    /* offset from start of file */
  119. #elif OPSYS == OS_MAC
  120.  
  121. #elif OPSYS == OS_UNIX
  122.     int    cmd    = 0;    /* lock command */
  123.     struct flock lck;    /* lock structure */
  124. #elif OPSYS == OS_VMS
  125.  
  126. #endif
  127.     /* validate arguments */
  128.     if (!b_valid(bp)) {
  129.         errno = EINVAL;
  130.         return -1;
  131.     }
  132.  
  133.     /* check if not open */
  134.     if (!(bp->flags & BIOOPEN)) {
  135.         errno = BENOPEN;
  136.         return -1;
  137.     }
  138.  
  139.     /* set lock flags */
  140.     switch (ltype) {
  141.     case B_RDLCK:
  142.         if (!(bp->flags & BIOREAD)) {
  143.             errno = BENOPEN;
  144.             return -1;
  145.         }
  146. #if OPSYS == AMIGADOS
  147.  
  148. #elif OPSYS == OS_DOS
  149.         mode = LK_NBRLCK;
  150. #elif OPSYS == OS_MAC
  151.  
  152. #elif OPSYS == OS_UNIX
  153.         cmd = F_SETLK;
  154.         lck.l_type = F_RDLCK;
  155. #elif OPSYS == OS_VMS
  156.  
  157. #endif
  158.         break;
  159.     case B_RDLKW:
  160.         if (!(bp->flags & BIOREAD)) {
  161.             errno = BENOPEN;
  162.             return -1;
  163.         }
  164. #if OPSYS == AMIGADOS
  165.  
  166. #elif OPSYS == OS_DOS
  167.         mode = LK_RLCK;
  168. #elif OPSYS == OS_MAC
  169.  
  170. #elif OPSYS == OS_UNIX
  171.         cmd = F_SETLKW;
  172.         lck.l_type = F_RDLCK;
  173. #elif OPSYS == OS_VMS
  174.  
  175. #endif
  176.         break;
  177.     case B_WRLCK:
  178.         if (!(bp->flags & BIOWRITE)) {
  179.             errno = BENOPEN;
  180.             return -1;
  181.         }
  182. #if OPSYS == AMIGADOS
  183.  
  184. #elif OPSYS == OS_DOS
  185.         mode = LK_NBLCK;
  186. #elif OPSYS == OS_MAC
  187.  
  188. #elif OPSYS == OS_UNIX
  189.         cmd = F_SETLK;
  190.         lck.l_type = F_WRLCK;
  191. #elif OPSYS == OS_VMS
  192.  
  193. #endif
  194.         break;
  195.     case B_WRLKW:
  196.         if (!(bp->flags & BIOWRITE)) {
  197.             errno = BENOPEN;
  198.             return -1;
  199.         }
  200. #if OPSYS == AMIGADOS
  201.  
  202. #elif OPSYS == OS_DOS
  203.         mode = LK_LOCK;
  204. #elif OPSYS == OS_MAC
  205.  
  206. #elif OPSYS == OS_UNIX
  207.         cmd = F_SETLKW;
  208.         lck.l_type = F_WRLCK;
  209. #elif OPSYS == OS_VMS
  210.  
  211. #endif
  212.         break;
  213.     case B_UNLCK:
  214.         /* flush buffers */
  215.         if (bflush(bp) == -1) {
  216.             BEPRINT;
  217.             return -1;
  218.         }
  219. #if OPSYS == AMIGADOS
  220.  
  221. #elif OPSYS == OS_DOS
  222.         mode = LK_UNLCK;
  223. #elif OPSYS == OS_MAC
  224.  
  225. #elif OPSYS == OS_UNIX
  226.         cmd = F_SETLK;
  227.         lck.l_type = F_UNLCK;
  228. #elif OPSYS == OS_VMS
  229.  
  230. #endif
  231.         break;
  232.     default:
  233.         errno = EINVAL;
  234.         return -1;
  235.         break;
  236.     }
  237.  
  238.     /* lock */
  239. #ifndef SINGLE_USER
  240. #if OPSYS == AMIGADOS
  241.  
  242. #elif OPSYS == OS_DOS
  243.     if (start == 0) {
  244.         offset = 0;
  245.         if (len == 0) {
  246.             length = LONG_MAX;
  247.         } else {
  248.             length = bp->hdrsize + (len - 1) * bp->blksize;
  249.         }
  250.     } else {
  251.         offset = bp->hdrsize + (start - 1) * bp->blksize;
  252.         if (len == 0) {
  253.             length = LONG_MAX - offset;
  254.         } else {
  255.             length = len * bp->blksize;
  256.         }
  257.     }
  258. #if CCOM == CC_BC
  259.     switch (mode) {
  260.     case LK_UNLCK:    /* unlock */
  261.         if (unlock(bp->fd.i, offset, length) == -1) {
  262.             /* ignore 'segment not locked' error */
  263.             if (errno == EACCES) return 0;
  264.             return -1;
  265.         }
  266.         break;
  267.     default:    /* lock */
  268.         if (lock(bp->fd.i, offset, length) == -1) {
  269.             if (errno == EACCES) errno = EAGAIN;
  270.             if (errno != EAGAIN) BEPRINT;
  271.             return -1;
  272.         }
  273.         break;
  274.     }
  275. #elif CCOM == CC_MSC || CCOM == CC_MSQC
  276.     if (lseek(bp->fd.i, offset, SEEK_SET) == -1) {
  277.         BEPRINT;
  278.         return -1;
  279.     }
  280.     if (locking(bp->fd.i, mode, length) == -1) {
  281.         /* ignore 'segment not locked' error */
  282.         if (mode == LK_UNLCK) {
  283.             if (errno == EACCES) return 0;
  284.         }
  285.         if (errno == EACCES) errno = EAGAIN;
  286.         if (errno != EAGAIN) BEPRINT;
  287.         return -1;
  288.     }
  289. #endif
  290. #elif OPSYS == OS_MAC
  291.  
  292. #elif OPSYS == OS_UNIX
  293.     if (start == 0) {
  294.         lck.l_whence = 0;
  295.         if (len == 0) {
  296.             lck.l_len = 0;
  297.         } else {
  298.             lck.l_len = bp->hdrsize + (len - 1) * bp->blksize;
  299.         }
  300.     } else {
  301.         lck.l_whence = bp->hdrsize + (start - 1) * bp->blksize;
  302.         if (len == 0) {
  303.             lck.l_len = 0;
  304.         } else {
  305.             lck.l_len = len * bp->blksize;
  306.         }
  307.     }
  308.     lck.l_start = 0;
  309. /*    lck.l_sysid = 0; l_sysid not defined by BSD UNIX */
  310.     lck.l_pid = 0;
  311.     if (fcntl(bp->fd.i, cmd, &lck) == -1) {
  312.         /* new versions of fcntl will use EAGAIN */
  313.         if (errno == EACCES) errno = EAGAIN;
  314.         if (errno != EAGAIN) BEPRINT;
  315.         return -1;
  316.     }
  317. #elif OPSYS == OS_VMS
  318.  
  319. #endif
  320. #endif    /* #ifndef SINGLE_USER */
  321.  
  322.     /* if locking, load endblk */
  323.     if (ltype != B_UNLCK) {
  324.         if (b_uendblk(bp, &bp->endblk) == -1) {
  325.             BEPRINT;
  326.             return -1;
  327.         }
  328.     }
  329.  
  330.     return 0;
  331. }
  332.